// ActionNode.java
package org.zjx.core.nodes;

import lombok.Data;
import lombok.Setter;
import org.zjx.core.DecisionContext;
import org.zjx.core.DecisionNode;
import org.zjx.core.DecisionStack;
import org.zjx.core.GameAction;

/**
 * 动作节点 - 执行具体游戏动作的决策节点
 *
 * 功能说明：
 * 1. 封装一个具体的游戏动作(GameAction)
 * 2. 在执行动作后将控制流转移到下一个节点(如果存在)
 * 3. 通过DecisionStack管理决策调用栈，支持中断和回溯
 *
 * 使用场景：
 * - 当决策树需要执行具体游戏操作时使用此节点
 * - 通常作为条件分支节点的后续节点
 */
@Data
public class ActionNode implements DecisionNode {
    /**
     * 要执行的动作
     * 不可为null，必须在构造时提供有效的GameAction实例
     */
    private final GameAction action;

    /**
     * 下一个决策节点
     * 可以为null，表示这是决策路径的终点
     */
    private DecisionNode next;

    /**
     * 构造函数
     * @param action 要执行的动作(不可为null)
     * @param next 下一个节点(可为null)
     * @throws IllegalArgumentException 如果action参数为null
     */
    public ActionNode(GameAction action, DecisionNode next) {
        if (action == null) {
            throw new IllegalArgumentException("Action cannot be null");
        }
        this.action = action;
        this.next = next;
    }

    /**
     * 执行决策逻辑
     * @param context 决策上下文，包含状态访问器、参数等信息
     * @return 总是返回封装的动作对象
     *
     * 方法行为：
     * 1. 如果存在下一个节点，将节点压入调用栈
     * 2. 返回封装的动作对象
     *
     * 注意：
     * - 此节点不直接执行动作，只是返回动作对象
     * - 实际动作执行由决策引擎在适当的时候调用
     */
    @Override
    public GameAction decide(DecisionContext context) {
        if (next != null) {
            // 将下一个节点压入调用栈，保存当前状态快照
            context.getCallStack().push(new DecisionStack.Frame(
                    next,
                    context.getStateAccessor()
            ));
        }
        return action;  // 返回封装的动作对象
    }
}